<template>
  <div class="tool-bar">
    <div class="bar-btn">
      <div v-for="(item, index) in btnList" :key="index" :class="{ 'is-select': item.isCheck }" class="btn-item"
           @click="clickBtn(item)">
        <span>{{ item.name }}</span>
      </div>
    </div>

    <div class="bar-control">
      <div v-for="(item, index) in controlList" :key="index"
           :class="{ 'is-select': item.isCheck, 'control-item-active': (isOpenLogic && item.name === '逻辑单体化') }"
           class="control-item">
        <div class="control-box" @click="clickControl(item, index)">
          <img :src="require(`@/assets/image/toolBar/${item.name}.png`)" alt="">
          <span>{{ item.name }}</span>
        </div>
      </div>
    </div>

    <path-roaming v-if="showRoaming" @close="closeRoaming"></path-roaming>
    <measurement v-if="showMeasurement" @close="closeMeasurement"></measurement>
    <position-adjust v-if="showAdjust" @close="closeAdjust"></position-adjust>
    <about-dialog v-if="showAbout" @close="closeAbout"></about-dialog>
    <sun-light v-if="showSun" @close="closeSun"></sun-light>
    <logic-dialog v-if="showLogicDialog" @close="closeLogic" @confirm="logicConfirm"></logic-dialog>
    <logic-popup ref="logicPopup" :data="popupData"></logic-popup>
    <pickup-popup ref="pickupPopup"></pickup-popup>
    <model-conversion v-if="modelConverShow" @close="modelConverShow = false"></model-conversion>
    <model-lightweight v-if="lightweightShow" @close="lightweightShow = false"></model-lightweight>
    <global-setting v-if="settingShow" @cancel="settingShow = false"></global-setting>
    <point-cloud v-if="pointCloudShow"></point-cloud>
    <single-conversion v-if="singleShow"></single-conversion>
  </div>
</template>

<script>
const fs = window.require('fs');
const {ipcRenderer} = window.require('electron');
import logicDialog from './logicDialog';
import logicPopup from './logicDialog/logicPopup.vue'
import pickupPopup from './pickup/popup.vue'
import pathRoaming from '@/components/toolBar/pathRoaming';
import measurement from '@/components/toolBar/measurement';
import positionAdjust from '@/components/toolBar/positionAdjust';
import aboutDialog from '@/components/toolBar/aboutDialog';
import sunLight from '@/components/toolBar/sunLight';
import logicMixin from './logicDialog/logicMixin';
import modelConversion from './modelConversion'
import modelLightweight from './modelLightweight'
import globalSetting from './globalSetting'
import pickupMixin from './pickup/pickupMixin'
import pointCloud from "./pointCloud";
import singleConversion from "./singleConversion";

export default {
  components: {
    pathRoaming,
    measurement,
    positionAdjust,
    aboutDialog,
    sunLight,
    logicDialog,
    logicPopup,
    modelConversion,
    modelLightweight,
    globalSetting,
    pickupPopup,
    pointCloud,
    singleConversion
  },
  mixins: [logicMixin, pickupMixin],
  data() {
    return {
      btnList: [
        {
          name: '工程',
          isCheck: true,
          controlList: [
            {
              name: '打开'
            },
            {
              name: '保存'
            },
            {
              name: '另存为'
            },
            {
              name: '设置'
            },
            {
              name: '退出'
            }
          ]
        },
        {
          name: '显示',
          isCheck: false,
          controlList: [
            {
              name: '纹理'
            },
            {
              name: '线框'
            },
            {
              name: '双面'
            },
            {
              name: '双屏对比'
            }
          ]
        },
        {
          name: '视图',
          isCheck: false,
          controlList: [
            {
              name: '前视图'
            },
            {
              name: '后视图'
            },
            {
              name: '左视图'
            },
            {
              name: '右视图'
            },
            {
              name: '俯视图'
            },
            // {
            //   name: '仰视图'
            // },
            {
              name: '路径漫游'
            }
          ]
        },
        {
          name: '工具',
          isCheck: false,
          controlList: [
            {
              name: '量测'
            },
            {
              name: '位置调整'
            },
            {
              name: '日照'
            },
            {
              name: '逻辑单体化',
              isCheck: false
            },
            {
              name: '倾斜模型转换'
            },
            {
              name: '模型轻量化'
            },
            {
              name: '点云数据转换'
            },
            {
              name: '单体模型转换'
            },
            {
              name: '拾取'
            }
          ]
        },
        {
          name: '帮助',
          isCheck: false,
          controlList: [
            {
              name: '帮助文档'
            },
            {
              name: '关于'
            }
          ]
        }
      ],
      controlList: [],
      openFileData: null,
      uploadFiles: [],
      showRoaming: false,
      showMeasurement: false,
      showAdjust: false,
      showAbout: false,
      showSun: false,
      isOpenLogic: false,
      showLogicDialog: false,
      modelConverShow: false,
      lightweightShow: false,
      pointCloudShow: false,
      settingShow: false,
      singleShow: false
    };
  },
  methods: {
    openSetting() {
      this.settingShow = true
    },
    // 按钮点击
    clickBtn(option) {
      if (option.isCheck) return;

      this.btnList.forEach(item => {
        item.isCheck = item.name === option.name;
      });
      this.controlList = this.btnList.find(e => {
        return e.isCheck;
      }).controlList;
    },

    // 控件点击
    clickControl(option, index) {
      const steadyLight = () => {
        let controlList = this.controlList;
        controlList.forEach(item => {
          if (item.name === option.name) {
            item.isCheck = !item.isCheck;
          }
        });
        this.controlList = [];
        this.controlList = controlList;
      };

      const flickerLight = () => {
        let controlList = this.controlList;
        setTimeout(() => {
          controlList.forEach(item => {
            if (item.name === option.name) {
              item.isCheck = false;
            }
            this.controlList = [];
            this.controlList = controlList;
          });
        }, 100);
      };

      switch (option.name) {
        case '纹理':
        case '线框':
        case '双面':
        case '双屏对比':
        case '路径漫游':
        case '量测':
        case '位置调整':
        case '日照':
          steadyLight();
          break;

        default:
          flickerLight();
          break;
      }

      switch (option.name) {
        case '打开':
          this.openFile();
          break;
        case '逻辑单体化':
          this.isOpenLogic = !this.isOpenLogic;
          if (this.isOpenLogic) {
            this.openLogic()
          } else {
            this.removeMaskAndFrame()
            this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
          }
          break;
        case '拾取':
          this.showPickup = !this.showPickup
          if (this.showPickup) {
            this.openPickup()
          } else {
            this.closePickup()
          }
          break
        case '倾斜模型转换':
          this.modelConverShow = true
          break;
        case '模型轻量化':
          this.lightweightShow = true
          break
        case '点云数据转换':
          this.pointCloudShow = true
          break
        case '单体模型转换':
          this.singleShow = true
          break
        case '保存':
          this.saveFile();
          break;
        case '设置':
          this.openSetting()
          break

        case '另存为':
          this.saveAsFile();
          break;

        case '退出':
          this.$confirm('确定退出', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            ipcRenderer.send('app-exit');
          });
          break;

        case '纹理':
          this.modelTexture(option.isCheck);
          break;

        case '线框':
          this.modelWireframe(option.isCheck);
          break;

        case '双面':
          this.modelBackFaceCulling(option.isCheck);
          break;

        case '双屏对比':
          this.$emit('clickControl', {name: option.name, isCheck: option.isCheck});
          break;


        case '前视图':
        case '后视图':
        case '左视图':
        case '右视图':
        case '俯视图':
        case '仰视图':
          this.switchView(option.name);
          break;

        case '路径漫游':
          this.showRoaming = option.isCheck;
          break;

        case '量测':
          this.showMeasurement = option.isCheck;
          break;

        case '位置调整':
          this.showAdjust = option.isCheck;
          break;

        case '日照':
          this.showSun = option.isCheck;
          break;

        case '关于':
          this.showAbout = true;
          break;

        default:
          break;
      }
    },
    // 打开逻辑单体化
    openLogic() {
      if (this.isSelectData()) {
        this.showLogicDialog = true
      } else {
        this.isOpenLogic = false
      }
    },
    // 判断是否已经选择了三维数据和矢量数据
    isSelectData() {
      const treeData = this.$store.state.treeData
      const tileLength = treeData[0].children[0].children.length
      const vectorLength = treeData[0].children[1].children.length
      if (tileLength && vectorLength) {
        return true
      }
      if (!tileLength && !vectorLength) {
        this.$message.error('请添加三维数据和矢量数据')
        return false
      } else {
        if (!tileLength) {
          this.$message.error('请添加三维数据')
        }
        if (!vectorLength) {
          this.$message.error('请添加矢量数据')
        }
        return false
      }
    },
    /**
     * 开始
     */
    // 打开
    openFile() {
      const option = {
        filters: [{name: 'file', extensions: ['3dvp']}]
      }
      ipcRenderer.send('show-open-dialog', option);
      ipcRenderer.once('show-open-dialog', (event, data) => {
        const {filePath, fileSize, fileContent} = data;
        if (!filePath) {
          return;
        } else if (!fileContent) {
          this.message('文件为空');
          return;
        } else if (fileSize > 10) {
          this.message('文件大小超过10MB');
          return;
        }
        const info = JSON.parse(fileContent);
        if (info.type != '3dViewer') {
          this.message('请选择 type为 3dViewer的文件');
          return;
        }
        this.eventBus.$emit('loadFile', info.data);
        window.sessionStorage.setItem('openFileData', JSON.stringify(data));
      });
    },

    // 保存文件
    saveFile() {
      let openFileData = window.sessionStorage.getItem('openFileData');
      if (openFileData) {
        const fileData = JSON.parse(openFileData);
        const {filePath} = fileData;
        if (!fs.existsSync(filePath)) {
          this.saveAsFile();
          return;
        }
        const fileContent = this.getSaveContent();
        if (!fileContent) {
          this.saveAsFile();
          return;
        }
        fs.writeFileSync(filePath, fileContent);
        this.message('保存成功', 'success');
      } else {
        this.saveAsFile();
      }
    },

    // 另存为
    saveAsFile() {
      const fileContent = this.getSaveContent();
      ipcRenderer.send('show-save-dialog', {fileContent: fileContent});
      ipcRenderer.on('show-save-dialog', (event, data) => {
        console.log(data)
        window.sessionStorage.setItem('openFileData', JSON.stringify(data));
        this.message('另存成功', 'success');
      });
    },

    getSaveContent() {
      this.eventBus.$emit('getTreeData');
      let treeData = JSON.parse(JSON.stringify(this.Global.treeData));
      let fileContent = null;
      if (this.viewer) {
        let content = {
          type: '3dViewer',
          data: treeData
        };
        fileContent = JSON.stringify(content);
        console.log(content);
      }
      return fileContent;
    },

    /**
     * 显示
     * */
    // 纹理
    modelTexture(state) {
      if (!this.viewer || !this.viewer.scene.primitives || !this.viewer.scene.primitives._primitives || !this.viewer.scene.primitives._primitives.length) return;
      let tilePrimitives = this.viewer.scene.primitives._primitives.filter(e => {
        return e instanceof Cesium.Cesium3DTileset;
      });
      if (!tilePrimitives.length) return;
      this.createdCustomShader();
      let defaultCustomShader = new Cesium.CustomShader({
        lightingModel: Cesium.LightingModel.UNLIT
      })
      tilePrimitives.forEach(item => {
        item.customShader = state ? this.customShader : defaultCustomShader;
      });
    },

    createdCustomShader() {
      if (this.customShader) return;
      this.customShader = new Cesium.CustomShader({
        // lightingModel: Cesium.LightingModel.UNLIT,
        //  lightingModel: Cesium.LightingModel.PBR,
        // 设置变量，由顶点着色器传递给片元着色器
        varyings: {
          v_normalMC: Cesium.VaryingType.VEC3,
          v_st: Cesium.VaryingType.VEC3
        },
        // 外部传给顶点着色器或者片元着色器
        uniforms: {
          u_texture: {
            value: new Cesium.TextureUniform({
              url: require('@/assets/image/toolBar/R-C2.jpg')
            }),
            type: Cesium.UniformType.SAMPLER_2D
          }
        },
        // 贴纹理
        // 顶点着色器
        // 将法向量从顶点着色器设置变量传给片元着色器
        vertexShaderText: `
            void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
                  v_normalMC = vsInput.attributes.normalMC;
                  v_st=vsInput.attributes.positionMC;   
            }`,
        // 片元着色器
        fragmentShaderText: `
           void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
              vec3 positionMC = fsInput.attributes.positionMC;
              // 这里是设置要贴图的图片的尺寸，设置小了会重复
              float width = 37.0;
              float height = 40.0;
              vec3 rgb;
              // 这是是设置了屋顶的颜色，当和法向量平行时，就是屋顶，这里设置0.95，相当于垂直，建筑物四周开始贴图
              if (dot(vec3(0.0, 1.0, 0.0), v_normalMC) > 0.95) {
                material.diffuse = vec3(1.0, 0.0, 0.0);
              } else {
                float textureX = 0.0;
                float dotYAxis = dot(vec3(0.0, 0.0, 1.0), v_normalMC);
                // cos(45deg) 约等于 0.71，这里是建筑物四周的向量与法向量会大于四十五度夹角
                if (dotYAxis > 0.71 || dotYAxis < -0.71) {
                // x代表的是前后面
                  textureX = mod(positionMC.x, width) / width;
                } else {
                // z代表的是左右面
                  textureX = mod(positionMC.z, width) / width;
                }
                float textureY = mod(positionMC.y, height) / height;
                rgb = texture(u_texture, vec2(textureX, textureY)).rgb;
                material.diffuse = rgb;
              }
          }`
      });
    },

    // 线框
    modelWireframe(state) {
      if (!this.viewer || !this.viewer.scene.primitives || !this.viewer.scene.primitives._primitives || !this.viewer.scene.primitives._primitives.length) return;
      let tilePrimitives = this.viewer.scene.primitives._primitives.filter(e => {
        return e instanceof Cesium.Cesium3DTileset;
      });
      if (!tilePrimitives.length) return;
      tilePrimitives.forEach(item => {
        item.debugShowBoundingVolume = state;
      });
    },

    // 双面
    modelBackFaceCulling(state) {
      if (!this.viewer || !this.viewer.scene.primitives || !this.viewer.scene.primitives._primitives || !this.viewer.scene.primitives._primitives.length) return;
      let tilePrimitives = this.viewer.scene.primitives._primitives.filter(e => {
        return e instanceof Cesium.Cesium3DTileset;
      });
      if (!tilePrimitives.length) return;
      tilePrimitives.forEach(item => {
        item.backFaceCulling = state;
      });
    },

    /**
     * 视图
     * */
    switchView(option) {
      const viewPosition = this.getViewer();
      let orientation = {};
      switch (option) {
        case '前视图':
          orientation = {
            heading: 0,
            pitch: 0,
            roll: 0
          };
          break;

        case '后视图':
          orientation = {
            heading: 180,
            pitch: 0,
            roll: 0
          };
          break;

        case '左视图':
          orientation = {
            heading: 270,
            pitch: 0,
            roll: 0
          };
          break;

        case '右视图':
          orientation = {
            heading: 90,
            pitch: 0,
            roll: 0
          };
          break;

        case '俯视图':
          orientation = {
            heading: 0,
            pitch: -90,
            roll: 0
          };
          break;

        case '仰视图':
          orientation = {
            heading: 180,
            pitch: 90,
            roll: 0
          };
          break;

        default:
          break;
      }
      this.flyTo({...viewPosition.position, ...orientation});
    },

    getViewer() {
      const viewer = this.viewer;
      let cartesian = viewer.camera.position.clone();
      let ellipsoid = this.viewer.scene.globe.ellipsoid;
      let cartographic = ellipsoid.cartesianToCartographic(cartesian);
      let lat = Cesium.Math.toDegrees(cartographic.latitude);
      let lng = Cesium.Math.toDegrees(cartographic.longitude);
      let height = cartographic.height;
      return {
        cartesian,
        position: {lat, lng, height},
        orientation: {
          heading: viewer.camera.heading,
          pitch: viewer.camera.pitch,
          roll: viewer.camera.roll
        }
      };
    },

    flyTo(position, callback) {
      const {lng, lat, height, heading, pitch, roll} = position;
      if (!lng || !lat || !height) return;
      this.viewer.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(lng, lat, height),
        orientation: {
          heading: Cesium.Math.toRadians(heading),
          pitch: Cesium.Math.toRadians(pitch),
          roll: Cesium.Math.toRadians(roll)
        },
        complete: callback && callback()
      });
    },

    closeRoaming() {
      this.showRoaming = false;
      let btnList = this.btnList;
      btnList.forEach(item => {
        if (item.name == '视图') {
          item.controlList.map(e => {
            return e.name == '路径漫游' && (e.isCheck = false);
          });
        }
      });
      this.btnList = btnList;
    },

    /**
     * 工具
     * */
    closeMeasurement() {
      this.showMeasurement = false;
      let btnList = this.btnList;
      btnList.forEach(item => {
        if (item.name == '工具') {
          item.controlList.map(e => {
            return e.name == '量测' && (e.isCheck = false);
          });
        }
      });
      this.btnList = btnList;
    },

    closeAdjust() {
      this.showAdjust = false;
      let btnList = this.btnList;
      btnList.forEach(item => {
        if (item.name == '工具') {
          item.controlList.map(e => {
            return e.name == '位置调整' && (e.isCheck = false);
          });
        }
      });
      this.btnList = btnList;
    },

    closeSun() {
      this.showSun = false;
      let btnList = this.btnList;
      btnList.forEach(item => {
        if (item.name == '工具') {
          item.controlList.map(e => {
            return e.name == '日照' && (e.isCheck = false);
          });
        }
      });
      this.btnList = btnList;
    },

    /**
     * 帮助
     * */
    closeAbout() {
      this.showAbout = false;
    },

    // 提示
    message(message = '警告', type = 'warning') {
      this.$message({
        message: message,
        type: type
      });
    }
  },

  created() {
    this.controlList = this.btnList.find(e => {
      return e.isCheck;
    }).controlList;
    this.customShader = null;
  },

  mounted() {
    this.viewer = this.Global.viewer;
  },

  beforeDestroy() {
    this.customShader = null;
    window.sessionStorage.setItem('openFileData', '');
    this.modelTexture(false);
    this.modelWireframe(false);
  }
}
</script>

<style lang="less" scoped>
.tool-bar {
  width: 100%;
  height: 100%;

  .bar-btn {
    display: flex;
    align-items: center;
    height: 30px;

    .btn-item {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 62px;
      height: 100%;
      font-size: 14px;
      color: #ffffff;
      cursor: pointer;
    }

    .is-select {
      background: #444444;
      border-radius: 4px 4px 0px 0px;
    }
  }

  .bar-control {
    display: flex;
    align-items: center;
    height: 64px;
    border-top: 1px solid #444444;
    gap: 10px;

    .control-item {
      width: 72px;
      height: 100%;
      cursor: pointer;

      &:hover {
        background: rgba(74, 88, 120, 0.4);
      }

      img {
        width: 28px;
        height: 28px;
        margin-bottom: 6px;
      }

      .control-box,
      /deep/ .upload-btn,
      /deep/ .el-upload {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        width: 100%;
        height: 100%;
        font-size: 12px;
        color: #ffffff !important;
      }
    }

    .control-item-active {
      background: rgba(74, 88, 120, 0.4);
    }

    .is-select {
      background: rgba(74, 88, 120, 0.4);
    }
  }
}
</style>